#include "hdl_oled.h"

uint8_t OLED_GRAM[144][8];

unsigned char BMP1[] =
{
	0x00,0x03,0x05,0x09,0x11,0xFF,0x11,0x89,0x05,0xC3,0x00,0xE0,0x00,0xF0,0x00,0xF8,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x28,0xFF,0x11,0xAA,0x44,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x01,0x38,0x44,0x82,0x92,
	0x92,0x74,0x01,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x44,0xFF,0x01,0x7D,
	0x7D,0x7D,0x01,0x7D,0x7D,0x7D,0x7D,0x01,0x7D,0x7D,0x7D,0x7D,0x7D,0x01,0xFF,0x00,
	0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,
	0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,
	0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x3F,0x03,0x03,
	0xF3,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x01,0xF1,0x11,0x61,0x81,0x01,0x01,0x01,
	0x81,0x61,0x11,0xF1,0x01,0x01,0x01,0x01,0x41,0x41,0xF1,0x01,0x01,0x01,0x01,0x01,
	0xC1,0x21,0x11,0x11,0x11,0x11,0x21,0xC1,0x01,0x01,0x01,0x01,0x41,0x41,0xF1,0x01,
	0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x11,0x11,0x11,0x11,0x11,0xD3,0x33,
	0x03,0x03,0x3F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0x00,0x00,
	0x7F,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x7F,0x00,0x00,0x01,0x06,0x18,0x06,
	0x01,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x40,0x40,0x7F,0x40,0x40,0x00,0x00,0x00,
	0x1F,0x20,0x40,0x40,0x40,0x40,0x20,0x1F,0x00,0x00,0x00,0x00,0x40,0x40,0x7F,0x40,
	0x40,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x40,0x30,0x0C,0x03,0x00,0x00,
	0x00,0x00,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x06,0x06,
	0x06,0x06,0x04,0x04,0x04,0x84,0x44,0x44,0x44,0x84,0x04,0x04,0x84,0x44,0x44,0x44,
	0x84,0x04,0x04,0x04,0x84,0xC4,0x04,0x04,0x04,0x04,0x84,0x44,0x44,0x44,0x84,0x04,
	0x04,0x04,0x04,0x04,0x84,0x44,0x44,0x44,0x84,0x04,0x04,0x04,0x04,0x04,0x84,0x44,
	0x44,0x44,0x84,0x04,0x04,0x84,0x44,0x44,0x44,0x84,0x04,0x04,0x04,0x04,0x06,0x06,
	0x06,0x06,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x10,0x18,0x14,0x12,0x11,0x00,0x00,0x0F,0x10,0x10,0x10,
	0x0F,0x00,0x00,0x00,0x10,0x1F,0x10,0x00,0x00,0x00,0x08,0x10,0x12,0x12,0x0D,0x00,
	0x00,0x18,0x00,0x00,0x0D,0x12,0x12,0x12,0x0D,0x00,0x00,0x18,0x00,0x00,0x10,0x18,
	0x14,0x12,0x11,0x00,0x00,0x10,0x18,0x14,0x12,0x11,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,
	0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x7F,0x03,0x0C,0x30,0x0C,0x03,0x7F,0x00,0x00,0x38,0x54,0x54,0x58,0x00,0x00,
	0x7C,0x04,0x04,0x78,0x00,0x00,0x3C,0x40,0x40,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xAA,0xAA,0xAA,
	0x28,0x08,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x03,0x0C,0x30,0x0C,0x03,0x7F,
	0x00,0x00,0x26,0x49,0x49,0x49,0x32,0x00,0x00,0x7F,0x02,0x04,0x08,0x10,0x7F,0x00,/********************************/
};


int8_t hdl_oled_write_cmd(uint8_t dat,uint8_t mode)
{
	int8_t ret = SUCCESS;
	ret |= hal_i2c_analog_start();
	ret |= hal_i2c_analog_write(OLED_I2C_ADDRESS);
	ret |= hal_i2c_analog_wait_ack();
	if(mode)
	{
		ret |= hal_i2c_analog_write(0x40);
	}
  	else
	{
		ret |= hal_i2c_analog_write(0x00);
	}
	ret |= hal_i2c_analog_wait_ack();
	ret |= hal_i2c_analog_write(dat);
	ret |= hal_i2c_analog_wait_ack();
	ret |= hal_i2c_analog_stop();
	return ret;
}


void hdl_oled_draw_pt(uint8_t row,uint8_t col,uint8_t fill)
{
	uint8_t i,m,n;
	i = col >> 3;

	m = col%8;

	n = 1<<m;

	if(fill)
	{
		OLED_GRAM[row][i]|=n;
	}
	else
	{
		OLED_GRAM[row][i]=~OLED_GRAM[row][i];
		OLED_GRAM[row][i] |= n;
		OLED_GRAM[row][i]=~OLED_GRAM[row][i];
	}
}

//更新显存到OLED	
void hdl_oled_flash_show(void)
{
	uint8_t i,n;
	for(i=0;i<8;i++)
	{

		hdl_oled_write_cmd(0xb0+i,OLED_CMD); //设置行起始地址
		hdl_oled_write_cmd(0x00,OLED_CMD);   //设置低列起始地址
		hdl_oled_write_cmd(0x10,OLED_CMD);   //设置高列起始地址

		hal_i2c_analog_start();
		hal_i2c_analog_write(OLED_I2C_ADDRESS);
		hal_i2c_analog_wait_ack();
		hal_i2c_analog_write(0x40);
		hal_i2c_analog_wait_ack();
		for(n=0;n<128;n++)
		{
			hal_i2c_analog_write(OLED_GRAM[n][i]);
			hal_i2c_analog_wait_ack();
		}
		hal_i2c_analog_stop();
  }
}

void hdl_oled_screen_clr(void)
{
	uint8_t i,n;
	for(i=0;i<8;i++)
	{
		for(n=0;n<128;n++)
		{
			OLED_GRAM[n][i]=0;
		}
	}
	hdl_oled_flash_show();
}

void hdl_oled_show_picture(uint8_t x,uint8_t y,uint8_t sizex,uint8_t sizey,uint8_t BMP[],uint8_t mode)
{
	uint16_t j=0;
	uint8_t i,n,temp,m;
	uint8_t x0=x,y0=y;

	sizey = (sizey>>3) + ((sizey % 8)?1:0);
	for(n=0;n<sizey;n++)
	{
		for(i=0;i<sizex;i++)
		{
			temp=BMP[j];
			j++;
			for(m=0;m<8;m++)
			{
				if(temp&0x01)
				{
					hdl_oled_draw_pt(x,y,mode);
				}
				else
				{
					hdl_oled_draw_pt(x,y,!mode);
				}
				temp >>= 1;
				y++;
			}
			x++;
			if((x-x0)==sizex)
			{
				x=x0;
				y0=y0+8;
			}
			y=y0;
		}
	}
	hdl_oled_flash_show();
}

int8_t hdl_oled_cfg(void)
{
	int8_t ret = SUCCESS;
	ret |= hdl_oled_write_cmd(0xAE,OLED_CMD);//--turn off oled panel
	ret |= hdl_oled_write_cmd(0x00,OLED_CMD);//---set low column address
	ret |= hdl_oled_write_cmd(0x10,OLED_CMD);//---set high column address
	ret |= hdl_oled_write_cmd(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
	ret |= hdl_oled_write_cmd(0x81,OLED_CMD);//--set contrast control register
	ret |= hdl_oled_write_cmd(0xCF,OLED_CMD);// Set SEG Output Current Brightness
	ret |= hdl_oled_write_cmd(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
	ret |= hdl_oled_write_cmd(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
	ret |= hdl_oled_write_cmd(0xA6,OLED_CMD);//--set normal display
	ret |= hdl_oled_write_cmd(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
	ret |= hdl_oled_write_cmd(0x3f,OLED_CMD);//--1/64 duty
	ret |= hdl_oled_write_cmd(0xD3,OLED_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
	ret |= hdl_oled_write_cmd(0x00,OLED_CMD);//-not offset
	ret |= hdl_oled_write_cmd(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
	ret |= hdl_oled_write_cmd(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
	ret |= hdl_oled_write_cmd(0xD9,OLED_CMD);//--set pre-charge period
	ret |= hdl_oled_write_cmd(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
	ret |= hdl_oled_write_cmd(0xDA,OLED_CMD);//--set com pins hardware configuration
	ret |= hdl_oled_write_cmd(0x12,OLED_CMD);
	ret |= hdl_oled_write_cmd(0xDB,OLED_CMD);//--set vcomh
	ret |= hdl_oled_write_cmd(0x40,OLED_CMD);//Set VCOM Deselect Level
	ret |= hdl_oled_write_cmd(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
	ret |= hdl_oled_write_cmd(0x02,OLED_CMD);//
	ret |= hdl_oled_write_cmd(0x8D,OLED_CMD);//--set Charge Pump enable/disable
	ret |= hdl_oled_write_cmd(0x14,OLED_CMD);//--set(0x10) disable
	ret |= hdl_oled_write_cmd(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
	ret |= hdl_oled_write_cmd(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) 
	hdl_oled_screen_clr();
	ret |= hdl_oled_write_cmd(0xAF,OLED_CMD);
	return ret;
}


int8_t hdl_oled_init(void)
{
	int8_t ret = FAIL;
	ret = hdl_oled_cfg();
	hdl_oled_show_picture(0,0,128,64,BMP1,1);
	DBG_INFO("OLED init %s\r\n",ret==SUCCESS?"pass":"fail");
	return ret;
}

struct hal_oled_if g_hdl_oled_if = 
{
	.oled_init = hdl_oled_init,
};